#!/usr/bin/env ruby
module RedBook
	
	unless const_defined?(:CONFIG) || const_defined?(:TEST_HOME)
		cfg_file = File.exist?("#{ENV['HOME']}/rbconfig.yml") ? "#{ENV['HOME']}/rbconfig.yml" : "#{RedBook::EXEHOME}/rbconfig.yml"
		if cfg_file == "#{RedBook::EXEHOME}/rbconfig.yml" && RedBook::MODE == 'gem' then
			begin
				raise GenericError, "HOME environment variable not set." unless ENV['HOME']
				if File.exist?(ENV['HOME']) then
				File.move("#{RedBook::EXEHOME}/rbconfig.yml", ENV['HOME'])
				else
					raise GenericError, "Unable to move default configuration file to HOME folder"
				end
				puts " Default configuration file was saved to #{ENV['HOME']}"
				RedBook::CONFIG = "#{ENV['HOME']}/rbconfig.yml"
			rescue Exception => e
				puts " #{e.class.to_s.underscore.titleize}: #{e.to_s}"
				puts " Exiting..." 
			end
		else
			RedBook::CONFIG = cfg_file
		end
	end
end

# This class is used as a frontend to access RedBook::Logger from command prompt.
class RedBook::Interface

	include RedBook::Utils

	# Initialize a renderer and a logger, define the RedBook::Logger#interface_input method,
	# add itself as a logger observer and starts the logger.
	def initialize
		@hooks = RedBook::HookCollection.new
		@renderer = RedBook::Renderer.new
		@directives = []
		RedBook::SHORTCUTS.each_pair do |j, k|
			RedBook::define_shortcut(j, k)
		end
		RedBook::Parser.directives.each { |d| @directives << ":#{d.to_s}" }
		@logger = RedBook::Logger.new
		@logger.interface_input = lambda { |sentence, object, regex_positive, regex_negative| input(sentence, object, regex_positive, regex_negative) }
		@logger.add_observer(self)
		@logger.start
		RedBook::LOADED_PLUGINS.each do |p|
			send :"initialize_#{p}" if respond_to?(:"initialize_#{p}")
		end
	end

	# Input method used as RedBook::Logger#interface_input
	def input(sentence, object, regex_positive, regex_negative=nil)
		@renderer.render({:warning => "#{sentence} [type 'e' to exit]: "})
		display
		print "   >> [input]: "
		answer = gets.chomp
		while !answer.match(regex_positive) && !answer.match(/[eE]/) do
			@renderer.render({:warning => "Invalid #{object}!"})
			display
			@renderer.render({:warning => "#{sentence} [type 'e' to exit]: "})
			display
			print "   >> [input]: "
			answer = gets.chomp
		end
		@renderer.reset
		answer = (answer.match(/[eE]/) || answer.match(regex_negative)) ? nil : answer
	end

	# Display logger notifications.
	def update(element, options)
		if element.name == :input then
			input
		else
			### HOOK
			unless @hooks.exec(:update, {:element => element, :options => options}) then
				@renderer.render(element, options)
				display
				@renderer.reset
			end
		end
	end

	# Start the main loop and process user input.
	def start
		while true do
			# Setup completion
			modified_tags = []
			@logger.tags.each do |e|
				modified_tags << '!'+e
				modified_tags << '+'+e
				modified_tags << '-'+e
			end
			completion_proc = lambda do |i|
				(@directives+@logger.tags+modified_tags+RedBook::Config.instance.macros_array).find_all	{ |e| e.to_s.match(/^#{Regexp.escape(i)}/) }
			end
			RedBook::rawline_editor.completion_proc = 	completion_proc
			# Show prompt
			prompt = instance_eval(RedBook::PROMPT) || "[#{RedBook::NAME}]# "
			input = RedBook::rawline_editor.read(prompt)
			# Process the user command
			@logger.process(input)
		end
	end

	private

	def display
		@renderer.output.each { |e| puts e }
	end

end
